#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "ddxc.h"


int my_recv(int sockfd,void* buf,int length){
    if(buf== NULL){
        return -1;
    }
    int temp=0;
    int ftemp=0;
    if(length > BUF_SIZE){
        printf("length err\n");
        return -1;
    }
    while(1){

        ftemp=recv(sockfd,buf+temp,length - temp,0);//0 阻塞(发送的缓冲区满/网络阻塞);
        // printf("ftemp%d\n",ftemp);
        if(ftemp == -1){
            perror("my_send err");
            return -1;
        }
        temp+=ftemp;
        // printf("temp%d\n",temp);
        if(ftemp == 0){
            return temp;
        }
        if(temp >= length){
            break;
        }
        
    }
    return temp;
}

int my_send(int sockfd,const void* buf,int length){
    if(buf == NULL){
        return -1;
    }
    int temp=0;
    int ftemp=0;

    while(1){
        
        ftemp=send(sockfd,buf+temp,length - temp,0);//0 阻塞(发送的缓冲区满/网络阻塞);
        // printf("ftemp%d\n",ftemp);
        if(ftemp == -1){
            perror("my_send err");
            return -1;
        }
        temp+=ftemp;
        if(temp >= length){
            break;
        }
        
    }
    return temp;
}

long file_size(const char* filename){ //获取文件体积(返回文件大小)
    if(filename == NULL){
        return -1;
    }
    long temp =0;
    if(access(filename,F_OK) == 0){
        int fd_r = open(filename,O_RDONLY);
        if(fd_r == 0){
            perror("open err");
            return -1;
        }
        temp=lseek(fd_r,0,SEEK_END);

        close(fd_r);
    }else{
        return 0;
    }
    

    return temp;
}

int serializa_msg(void* node,int num){//将数值写入四个字节中（序列化）(主机到网络)
    if(node == NULL){
        return -1;
    }
    int* temp=(int*)node;
    (*temp)=htonl(num);
    return 0;
}

int serializa_msg_char(int sockfd,char* node,int num){//（序列化char）
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    (*node)=num;
    if(my_send(sockfd,node,CHAR_SIZE) == -1){//
        perror("serializa_msg_char err");
        return -1;
    }
    return 0;
}

int serializa_msg_short(int sockfd,short* node,int num){//(序列化short)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    (*node)=htons(num);
    if(my_send(sockfd,node,SHORT_SIZE) == -1){ 
        perror("send err");
        return -1;
    }
    (*node)=num;
    return 0;
}

int serializa_msg_int(int sockfd,int* node,int num){//(序列化int)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    (*node)=htonl(num);
    if(my_send(sockfd,node,INT_SIZE) == -1){
        perror("send err");
        return -1;
    }
    (*node)=num;
    return 0;
}

int serializa_msg_long(int sockfd,long* node,int num){//(序列化long)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    (*node)=htonl(num);
    if(my_send(sockfd,node,LONG_SIZE) == -1){ //将文件名，和已下载的字节数传到服务端
        perror("send err");
        return -1;
    }
    (*node)=num;
    return 0;
}

int serializa_msg_block(int sockfd,char* node,int num){//(序列化字符串)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(num <=0){
        return -1;
    }
    int* temp=(int*)node;
    (*temp)=htonl(num);
    // if(my_send(sockfd,node,num+INT_SIZE) == -1){ 
    //     perror("send err");
    //     return -1;
    // }
    return my_send(sockfd,node,num+INT_SIZE);
}

int unserializa_msg(void* node){//(反序列化)(网络到主机)
    if(node == NULL){
        return -1;
    }
    
    int* temp=(int*)node;
    (*temp)=ntohl((*temp));
    return (*temp);
}

int unserializa_msg_char(int sockfd,char* node){//(反序列化char)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(my_recv(sockfd,node,CHAR_SIZE) != CHAR_SIZE){ 
        perror("send err");
        return -1;
    }
    return 0;
}

int unserializa_msg_short(int sockfd,short* node){//(反序列化short)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(my_recv(sockfd,node,SHORT_SIZE) != SHORT_SIZE){ //将文件名，和已下载的字节数传到服务端
        perror("send err");
        return -1;
    }
    (*node)=ntohs(*node);
    return 0;
}

int unserializa_msg_int(int sockfd,int* node){//(反序列化int)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(my_recv(sockfd,node,INT_SIZE) != INT_SIZE){ //将文件名，和已下载的字节数传到服务端
        perror("send err");
        return -1;
    }
    (*node)=ntohl(*node);
    return 0;
}

int unserializa_msg_long(int sockfd,long* node){//(反序列化long)
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(my_recv(sockfd,node,LONG_SIZE) != LONG_SIZE){ //将文件名，和已下载的字节数传到服务端
        perror("send err");
        return -1;
    }
    (*node)=ntohl(*node);
    return 0;
}

int unserializa_msg_block(int sockfd,char* node){//(反序列化字符串)//返回接收到的有效字节数
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(my_recv(sockfd,node,INT_SIZE) != INT_SIZE){ //将文件名，和已下载的字节数传到服务端
        perror("recv err");
        return -1;
    }
    
    int num=unserializa_msg(node);
    memset(node,0,num+INT_SIZE);
    return my_recv(sockfd,(node),num);
}

/*
sockfd：为接收方套接字 // node:为传输数据的结构指针 //type:选择发送类型：char/short/int/long/string(流);
num:在传输string(流)的时候，num为传输的有效字节数;其他的，num为传输的具体数值;
*/
int sticky_packs_send_func(int sockfd,void* node,char type,long num){//解决沾包-发送方
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(serializa_msg_char(sockfd,node,type) == -1){//发送数据类型
        return -1;
    }
    if(type == CHAR_TYPE){
        if(serializa_msg_char(sockfd,node,(char)num) == -1){
            return -1;
        }
    }else if(type == INT_TYPE){
        if(serializa_msg_int(sockfd,node,(int)num) == -1){
            printf("send int err");
            return -1;
        }
        
    }else if(type == LONG_TYPE){
        if(serializa_msg_long(sockfd,node,num) == -1){
            return -1;
        }
        
    }else if(type == STRING_TYPE){
        
        return serializa_msg_block(sockfd,node,(int)num);
        
    }
    
    return 0;
}

/*
sockfd：为发送方套接字 // node:为传输数据的结构的指针 //type:用于接收，收到的数据类型：char/short/int/long/string(流);
*/
int sticky_packs_recv_func(int sockfd,void* node,char type){
    if(node == NULL){
        return -1;
    }
    if(sockfd <=0){
        return -1;
    }
    if(unserializa_msg_char(sockfd,&type) == -1){//发送数据类型
        return -1;
    }
    if(type == CHAR_TYPE){
        if(unserializa_msg_char(sockfd,(char*)node) == -1){
            return -1;
        }
    }else if(type == INT_TYPE){
        if(unserializa_msg_int(sockfd,(int*)node) == -1){
            return -1;
        }
        
    }else if(type == LONG_TYPE){
        if(unserializa_msg_long(sockfd,(long*)node) == -1){
            return -1;
        }
    }else if(type == STRING_TYPE){
        
        return unserializa_msg_block(sockfd,(char*)node);
    }
    
    return 0;
}

